package com.star.uc.contract.enums.password;

import com.star.common.core.context.SpringContext;
import com.star.uc.contract.dto.response.PasswordDTO;
import com.star.uc.infras.properties.SaTokenProperties;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * 密码加密类型（默认md5加盐）
 *
 * @author zhouhengzhe
 * @version 1.0
 * @date 2023/10/23 17:45
 */
@Getter
@AllArgsConstructor
public enum PasswordTypeEnum implements Password {

    DEFAULT("DEFAULT", "默认") {
        /**
         * 加盐加密
         *
         * @param password
         * @return 加密后的密码
         */
        @Override
        public PasswordDTO encrypt(String password) {
            return MD5.encrypt(password);
        }

        /**
         * 校验密码
         *
         * @param password   前段传过来的密码
         * @param dbPassword 数据库密码
         * @param salt       盐值
         * @return
         */
        @Override
        public boolean decrypt(String password, String dbPassword, String salt) {
            return MD5.decrypt(password, dbPassword, salt);
        }
    },
    MD5("MD5", "MD5加盐加密") {
        /**
         * 加盐加密
         *
         * @param password
         * @return 加密后的密码
         */
        @Override
        public PasswordDTO encrypt(String password) {
            //生成盐值,使用随机字符串UUID，UUID为32位的
            String salt = UUID.randomUUID().toString().replace("-", "");
            //（盐值+密码）进行MD5加密,DigestUtils.md5DigestAsHex参数为字节数组,生成一个十六进制32位的字符串
            String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));
            //将盐值和加密的密码组合返回,最终存储到数据库中的密码
            return new PasswordDTO(finalPassword, salt);
        }

        /**
         * 校验密码
         *
         * @param password   前段传过来的密码
         * @param dbPassword 数据库密码
         * @param salt       盐值
         * @return
         */
        @Override
        public boolean decrypt(String password, String dbPassword, String salt) {
            if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) && StringUtils.hasLength(salt)) {
                //根据获取的盐值生成校验的密码
                String checkPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));
                //用校验密码与数据库保存的密码进行校验
                return checkPassword.equals(dbPassword);
            }
            return false;
        }
    },
    SHA256("SHA256", "SHA256加盐加密") {
        /**
         * 加盐加密
         *
         * @param password
         * @return 加密后的密码
         */
        @Override
        public PasswordDTO encrypt(String password) {
            return null;
        }

        /**
         * 校验密码
         *
         * @param password   前段传过来的密码
         * @param dbPassword 数据库密码
         * @param salt       盐值
         * @return
         */
        @Override
        public boolean decrypt(String password, String dbPassword, String salt) {
            return false;
        }
    },
    SHA512("SHA512", "SHA512加盐加密") {
        /**
         * 加盐加密
         *
         * @param password
         * @return 加密后的密码
         */
        @Override
        public PasswordDTO encrypt(String password) {
            return null;
        }

        /**
         * 校验密码
         *
         * @param password   前段传过来的密码
         * @param dbPassword 数据库密码
         * @param salt       盐值
         * @return
         */
        @Override
        public boolean decrypt(String password, String dbPassword, String salt) {
            return false;
        }
    };

    private final String code;
    private final String desc;

    /**
     * 匹配当前密码加密方式，返回对应得枚举类
     */
    public static PasswordTypeEnum match() {
        String passwordType = SpringContext.getBean(SaTokenProperties.class).getPasswordType();
        for (PasswordTypeEnum value : PasswordTypeEnum.values()) {
            if (value.code.equals(passwordType)) {
                return value;
            }
        }
        return PasswordTypeEnum.MD5;
    }
}
